package come.example.domain.strategy.service.rule.chain.factory;

import come.example.domain.strategy.model.entity.StrategyEntity;
import come.example.domain.strategy.repository.IStrategyRepository;
import come.example.domain.strategy.service.rule.chain.ILogicChain;
import lombok.*;
import org.springframework.stereotype.Service;

import java.util.Map;

@Service //工厂装配
public class DefaultChainFactory {

    // Spring 会自动将所有 ILogicChain 的实现类注入到这个 Map 中，Key 是 Bean 的名称（如 rule_blacklist）
    // 当在工厂类中通过Map<String, ILogicChain>注入时，这个Map的键就是这些Bean的名称，
    // 因此可以根据策略配置中的名称直接查找对应的Bean实例。就可以知道是用哪个logic函数去过滤了
    private final Map<String, ILogicChain> logicChainGroup;

    private IStrategyRepository repository;

    public DefaultChainFactory(Map<String, ILogicChain> logicChainGroup, IStrategyRepository repository) {
        this.logicChainGroup = logicChainGroup; // 所有规则链的实现（如黑名单、权重规则）
        this.repository = repository;
    }

    /**
     * 通过策略id，构建责任链
     * @param strategyId 策略id
     * @return LogicChain
     */
    public ILogicChain openLogicChain(Long strategyId) {
        // 通过策略ID查询数据库/缓存，获取该策略配置的责任链顺序（如 ["rule_blacklist", "rule_weight"]）。
        StrategyEntity strategy = repository.queryStrategyEntityByStrategyId(strategyId);
        String[] ruleModels = strategy.ruleModels();

        // 如果未配置策略规则，则只装填一个默认责任链
        if(null == ruleModels || ruleModels.length == 0) {
            // 这里就是几个规则链类前的@Component("rule_blacklist")
            return logicChainGroup.get("default");
        }

        // 按照配置顺序装填用户配置的责任链；rule_blacklist、rule_weight
        // 「注意此数据从Redis缓存中获取，如果更新库表，记得在测试阶段手动处理缓存」
        ILogicChain logicChain = logicChainGroup.get(ruleModels[0]);
        ILogicChain current = logicChain;
        for (int i = 1; i < ruleModels.length; i++) {
            // 获取 "rule_blacklist" 对应的实例
            ILogicChain nextChain = logicChainGroup.get(ruleModels[i]);
            current = current.appendNext(nextChain); // 每次迭代后，current指向链的末尾
        }

        // 责任链的最后装填默认责任链
        current.appendNext(logicChainGroup.get("default"));
        return logicChain; // 返回责任链头节点
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    public static class StrategyAwardVO {
        private Integer awardId;
        private String logicModel;
    }

    @Getter
    @AllArgsConstructor
    public enum LogicModel {
        RULE_DEFAULT("rule_default", "默认抽奖"),
        RULE_BLACKLIST("rule_blacklist", "黑名单抽奖"),
        RULE_WEIGHT("rule_weight", "权重规则"),

        ;
        private final String code;
        private final String info;
    }
}
